// NOTE: This example is just for illustration of one possible evolution of Async Move.
// Nothing here is implemented.#[actor]

/// This is an instance of the Account example using futures. See the README for semantics.
///
/// This model is similar as continuations, but uses a more intuitive way to chain execution steps, which is
/// also the dominant one in most modern programming languages.
module This::AccountFuture {

    use Async::Unit::Unit;
    use Async::Future::{Future, Cont, done, followed_by};

    #[state]
    struct Account {
        value: u64,
    }

    #[init]
    fun init(): Account {
        Account{value: 0}
    }

    #[rpc]
    fun deposit(this: &mut Account, v: u64): Future<Unit> {
        this.value = this.value + v;
        done()
    }

    #[rpc]
    fun withdraw(this: &mut Account, v: u64): Future<Unit> {
        this.value = this.value - v;
        done()
    }

    #[rpc]
    fun xfer(this: &Account, dest: address, v: u64): Future<Unit> {
        // Do not initiate the transfer if there are not enough funds.
        assert!(this.value >= v, 1);
        // Deposit on the other end, and only if this succeeds, withdraw here.
        followed_by(rpc_deposit(dest, v), cont_xfer_withdraw(v))
    }

    #[cont]
    fun xfer_withdraw(this: &mut Account, _previous: Unit, v: u64): Future<Unit> {
        withdraw(this, v)
    }

    // ===============================================================
    // The following native function definitions are automatically
    // generated by a Move attribute preprocessor, and implemented
    // automatically by the runtime environment.

    #[_generated_rpc]
    public native fun rpc_deposit(dest: address, v: u64): Future<Unit>;

    #[_generated_cont]
    native fun cont_xfer_withdraw(v: u64): Cont<Unit, Unit>;
}
